import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
import 'package:miracle_recorder/models/user_model.dart';
import 'package:miracle_recorder/models/topic_model.dart';
import 'package:miracle_recorder/models/livestream_model.dart';

class ApiService {
  static const String _baseUrl = 'http://localhost:8080/api/v1';
  static final Logger _logger = Logger();
  
  static late http.Client _client;
  
  static void init() {
    _client = http.Client();
  }
  
  static Future<Map<String, String>> _getHeaders() async {
    return {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    };
  }
  
  static Future<Map<String, String>> _getAuthHeaders() async {
    final token = await StorageService.getToken();
    return {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': 'Bearer $token',
    };
  }
  
  // Authentication
  static Future<UserModel> login(String email, String password) async {
    try {
      final response = await _client.post(
        Uri.parse('$_baseUrl/auth/login'),
        headers: await _getHeaders(),
        body: jsonEncode({
          'email': email,
          'password': password,
        }),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        await StorageService.saveToken(data['token']);
        return UserModel.fromJson(data['user']);
      } else {
        throw Exception('Login failed: ${response.body}');
      }
    } catch (e) {
      _logger.e('Login error: $e');
      throw Exception('Login failed: $e');
    }
  }
  
  static Future<UserModel> register(String username, String email, String password) async {
    try {
      final response = await _client.post(
        Uri.parse('$_baseUrl/auth/register'),
        headers: await _getHeaders(),
        body: jsonEncode({
          'username': username,
          'email': email,
          'password': password,
        }),
      );
      
      if (response.statusCode == 201) {
        final data = jsonDecode(response.body);
        await StorageService.saveToken(data['token']);
        return UserModel.fromJson(data['user']);
      } else {
        throw Exception('Registration failed: ${response.body}');
      }
    } catch (e) {
      _logger.e('Registration error: $e');
      throw Exception('Registration failed: $e');
    }
  }
  
  static Future<UserModel> refreshToken() async {
    try {
      final response = await _client.post(
        Uri.parse('$_baseUrl/auth/refresh'),
        headers: await _getAuthHeaders(),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        await StorageService.saveToken(data['token']);
        return UserModel.fromJson(data['user']);
      } else {
        throw Exception('Token refresh failed: ${response.body}');
      }
    } catch (e) {
      _logger.e('Token refresh error: $e');
      throw Exception('Token refresh failed: $e');
    }
  }
  
  // Topics
  static Future<List<TopicModel>> getTopics({int limit = 20, int offset = 0, String? category}) async {
    try {
      Uri url = Uri.parse('$_baseUrl/topics?limit=$limit&offset=$offset${category != null ? '&category=$category' : ''}');
      
      final response = await _client.get(
        url,
        headers: await _getAuthHeaders(),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        return (data['topics'] as List)
            .map((topic) => TopicModel.fromJson(topic))
            .toList();
      } else {
        throw Exception('Failed to get topics: ${response.body}');
      }
    } catch (e) {
      _logger.e('Get topics error: $e');
      throw Exception('Failed to get topics: $e');
    }
  }
  
  static Future<TopicModel> getTopic(int id) async {
    try {
      final response = await _client.get(
        Uri.parse('$_baseUrl/topics/$id'),
        headers: await _getAuthHeaders(),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        return TopicModel.fromJson(data['topic']);
      } else {
        throw Exception('Failed to get topic: ${response.body}');
      }
    } catch (e) {
      _logger.e('Get topic error: $e');
      throw Exception('Failed to get topic: $e');
    }
  }
  
  static Future<TopicModel> createTopic(Map<String, dynamic> topicData) async {
    try {
      final response = await _client.post(
        Uri.parse('$_baseUrl/topics'),
        headers: await _getAuthHeaders(),
        body: jsonEncode(topicData),
      );
      
      if (response.statusCode == 201) {
        final data = jsonDecode(response.body);
        return TopicModel.fromJson(data['topic']);
      } else {
        throw Exception('Failed to create topic: ${response.body}');
      }
    } catch (e) {
      _logger.e('Create topic error: $e');
      throw Exception('Failed to create topic: $e');
    }
  }
  
  // Livestreams
  static Future<List<LivestreamModel>> getLivestreams({int limit = 20, int offset = 0, String? status}) async {
    try {
      Uri url = Uri.parse('$_baseUrl/livestreams?limit=$limit&offset=$offset${status != null ? '&status=$status' : ''}');
      
      final response = await _client.get(
        url,
        headers: await _getAuthHeaders(),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        return (data['livestreams'] as List)
            .map((livestream) => LivestreamModel.fromJson(livestream))
            .toList();
      } else {
        throw Exception('Failed to get livestreams: ${response.body}');
      }
    } catch (e) {
      _logger.e('Get livestreams error: $e');
      throw Exception('Failed to get livestreams: $e');
    }
  }
  
  static Future<LivestreamModel> getLivestream(int id) async {
    try {
      final response = await _client.get(
        Uri.parse('$_baseUrl/livestreams/$id'),
        headers: await _getAuthHeaders(),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        return LivestreamModel.fromJson(data['livestream']);
      } else {
        throw Exception('Failed to get livestream: ${response.body}');
      }
    } catch (e) {
      _logger.e('Get livestream error: $e');
      throw Exception('Failed to get livestream: $e');
    }
  }
  
  static Future<LivestreamModel> createLivestream(Map<String, dynamic> livestreamData) async {
    try {
      final response = await _client.post(
        Uri.parse('$_baseUrl/livestreams'),
        headers: await _getAuthHeaders(),
        body: jsonEncode(livestreamData),
      );
      
      if (response.statusCode == 201) {
        final data = jsonDecode(response.body);
        return LivestreamModel.fromJson(data['livestream']);
      } else {
        throw Exception('Failed to create livestream: ${response.body}');
      }
    } catch (e) {
      _logger.e('Create livestream error: $e');
      throw Exception('Failed to create livestream: $e');
    }
  }
  
  static Future<void> startLivestream(int id) async {
    try {
      final response = await _client.post(
        Uri.parse('$_baseUrl/livestreams/$id/start'),
        headers: await _getAuthHeaders(),
      );
      
      if (response.statusCode != 200) {
        throw Exception('Failed to start livestream: ${response.body}');
      }
    } catch (e) {
      _logger.e('Start livestream error: $e');
      throw Exception('Failed to start livestream: $e');
    }
  }
  
  static Future<void> stopLivestream(int id) async {
    try {
      final response = await _client.post(
        Uri.parse('$_baseUrl/livestreams/$id/stop'),
        headers: await _getAuthHeaders(),
      );
      
      if (response.statusCode != 200) {
        throw Exception('Failed to stop livestream: ${response.body}');
      }
    } catch (e) {
      _logger.e('Stop livestream error: $e');
      throw Exception('Failed to stop livestream: $e');
    }
  }
  
  // File Upload
  static Future<String> uploadFile(File file) async {
    try {
      final request = http.MultipartRequest(
        'POST',
        Uri.parse('$_baseUrl/upload'),
      );
      
      request.headers.addAll(await _getAuthHeaders());
      request.files.add(await http.MultipartFile.fromPath('file', file.path));
      
      final response = await request.send();
      
      if (response.statusCode == 200) {
        final responseBody = await response.stream.bytesToString();
        final data = jsonDecode(responseBody);
        return data['url'];
      } else {
        throw Exception('File upload failed: ${response.statusCode}');
      }
    } catch (e) {
      _logger.e('File upload error: $e');
      throw Exception('File upload failed: $e');
    }
  }
  
  // AI Services
  static Future<String> summarizeContent(String content, {String? language, List<String>? keywords}) async {
    try {
      final response = await _client.post(
        Uri.parse('$_baseUrl/ai/summarize'),
        headers: await _getAuthHeaders(),
        body: jsonEncode({
          'content': content,
          'language': language,
          'keywords': keywords,
        }),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        return data['summary'];
      } else {
        throw Exception('Content summarization failed: ${response.body}');
      }
    } catch (e) {
      _logger.e('Content summarization error: $e');
      throw Exception('Content summarization failed: $e');
    }
  }
  
  static Future<String> generateSolution(int topicId, String content, String type, {List<String>? keywords}) async {
    try {
      final response = await _client.post(
        Uri.parse('$_baseUrl/ai/generate-solution'),
        headers: await _getAuthHeaders(),
        body: jsonEncode({
          'topic_id': topicId,
          'content': content,
          'type': type,
          'keywords': keywords,
        }),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        return data['solution'];
      } else {
        throw Exception('Solution generation failed: ${response.body}');
      }
    } catch (e) {
      _logger.e('Solution generation error: $e');
      throw Exception('Solution generation failed: $e');
    }
  }
  
  // User Profile
  static Future<UserModel> getProfile() async {
    try {
      final response = await _client.get(
        Uri.parse('$_baseUrl/user/profile'),
        headers: await _getAuthHeaders(),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        return UserModel.fromJson(data['user']);
      } else {
        throw Exception('Failed to get profile: ${response.body}');
      }
    } catch (e) {
      _logger.e('Get profile error: $e');
      throw Exception('Failed to get profile: $e');
    }
  }
  
  static Future<UserModel> updateProfile(Map<String, dynamic> profileData) async {
    try {
      final response = await _client.put(
        Uri.parse('$_baseUrl/user/profile'),
        headers: await _getAuthHeaders(),
        body: jsonEncode(profileData),
      );
      
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        return UserModel.fromJson(data['user']);
      } else {
        throw Exception('Failed to update profile: ${response.body}');
      }
    } catch (e) {
      _logger.e('Update profile error: $e');
      throw Exception('Failed to update profile: $e');
    }
  }
}